#include "contact.h"

//初始化函数的实现
//静态版本
// void InitContact(Contact* pc)
// {
//     assert(pc);
//     pc ->count = 0;
//     memset(pc->data,0,sizeof(pc->data));
// }
//动态版本

void CheckCapacity(Contact* pc)
{
    if(pc->count == pc->capacity)
    {
        Peoinfo* ptr = (Peoinfo*)realloc(pc->data,(pc->capacity + INC_SZ)*sizeof(Peoinfo));
        if(ptr == NULL)
        {
            printf("AddContact::%s\n",strerror(errno));
            return;
        }
        else
        {
            pc->data = ptr;
            pc->capacity += INC_SZ;
            printf("增容成功\n");
            printf("当前容量为%d\n",pc->capacity);
        }
    }
}

void LoadContact(Contact* pc)
{
    FILE* fpRead = fopen("contact.txt","rb");
    if(fpRead == NULL)
    {
        perror("LoadContact");
        return;
    }
    Peoinfo tmp = {0};
    while(fread(&tmp,sizeof(Peoinfo),1,fpRead))
    {
        CheckCapacity(pc);
        pc->data[pc->count]= tmp;
        pc->count++;
    }
    fclose(fpRead);
    fpRead = NULL;    
}
int InitContact(Contact* pc)
{
    assert(pc);
    pc ->count = 0;
    pc->data = (Peoinfo*)calloc(DEFAULT_SZ,sizeof(Peoinfo));
    //calloc等函数返回的指针记得检查
    if(pc->data == NULL)
    {
        printf("%s\n",strerror(errno));
        return 1;
    }
    pc->capacity = DEFAULT_SZ;
    //加载文件中的信息到通讯录中
    LoadContact(pc);
    return 0;
}

void DestoryContact(Contact* pc)
{
    free(pc->data);
    pc->data = NULL;
}

//添加成员的函数实现
//静态版本
// void AddContact(Contact* pc)
// {
//     if(pc->count == MAX)
//     {
//         printf("通讯录已满，无法添加\n");
//         return;
//     }
//     printf("请输入姓名：>\n");
//     scanf("%s",pc->data[pc->count].name);//name是数组名 所以不用取地址
//     printf("请输入年龄：>\n");
//     scanf("%d",&(pc->data[pc->count].age));//age是int型变量，所以需要取地址
//     printf("请输入电话：>\n");
//     scanf("%s",pc->data[pc->count].tel);
//     pc->count++;
//     printf("添加成功！\n");
// }


//动态版本
void AddContact(Contact* pc)
{
    CheckCapacity(pc);
    printf("请输入姓名：>\n");
    scanf("%s",pc->data[pc->count].name);//name是数组名 所以不用取地址
    printf("请输入年龄：>\n");
    scanf("%d",&(pc->data[pc->count].age));//age是int型变量，所以需要取地址
    printf("请输入电话：>\n");
    scanf("%s",pc->data[pc->count].tel);
    pc->count++;
    printf("添加成功！\n");
}


//打印函数的实现
void ShowContact(const Contact* pc)
{
    int i = 0;
    printf("%-10s\t%-5s\t%-20s\n","姓名","年龄","电话");//加符号可以实现左对齐
    for(i = 0;i < pc->count;i++)
    {
        printf("%-10s\t%-5d\t%-20s\n",pc->data[i].name,pc->data[i].age,pc->data[i].tel);
    }
}

//删除
static int FindByName(Contact* pc,char name[])//添加static可以使这个数据只在本代码中使用 避免暴露
{
    int i= 0;
    for(i = 0;i < pc ->count;i++)
    {
        if(0 == strcmp(pc->data[i].name,name))
        return i;
    }
    return -1;
}
void DelContact(Contact* pc)
{
    if(pc->count == 0)
    {
        printf("通讯录为空，没有可删除的信息\n");
        return;
    }
    char name[20] = { 0 };
    printf("请输入要删除联系人的姓名\n");
    scanf("%s",name);
    int pos = FindByName(pc,name);
    if(pos == -1)
    {
        printf("未查找到该联系人\n");
        return;
    }
    int i = 0;
    for(i = pos;i < pc->count -1;i++)//要考虑越界
    {
        pc->data[i] = pc->data[i+1];
    }
    pc->count--;//最后一个联系人不用处理，直接将联系人计数-1即可
    printf("删除成功\n");
}

//查找函数的实现
void SearchContact(Contact* pc)
{
    char name[20] = { 0 };
    printf("请输入要查找联系人的姓名\n");
    scanf("%s",name);
    int pos = FindByName(pc,name);
    if(pos == -1)
    {
        printf("未查找到该联系人\n");
        return;
    }
    printf("%-10s\t%-5s\t%-20s\n","姓名","年龄","电话");
    printf("%-10s\t%-5d\t%-20s\n",pc->data[pos].name,pc->data[pos].age,pc->data[pos].tel);
}

//修改函数的实现
void ModifyContact(Contact* pc)
{
    char name[20] = { 0 };
    printf("请输入要修改联系人的姓名\n");
    scanf("%s",name);
    int pos = FindByName(pc,name);
    if(pos == -1)
    {
        printf("未查找到该联系人\n");
        return;
    }
    printf("已查找到联系人，请输入要修改的内容\n");
    printf("请输入姓名：>\n");
    scanf("%s",pc->data[pos].name);
    printf("请输入年龄：>\n");
    scanf("%d",&(pc->data[pos].age));
    printf("请输入电话：>\n");
    scanf("%s",pc->data[pos].tel);
    printf("修改完成！\n");
}


//排序函数的实现
void SortByName(Contact* pc)
{
    int i = 0;
    for(i = 0;i < pc->count-1;i++)
    {
        int j = 0;
        //此处我用了冒泡排序，最好可以加上提前结束的判断
        int flag = 0;//是否发生过交换的标志
        for(j = 0;j < pc->count-1-i;j++)
        {

            if(strcmp(pc->data[j].name,pc->data[j+1].name)>0)
            {
                Peoinfo temp = pc->data[j];
                pc->data[j] = pc->data[j+1];
                pc->data[j+1] = temp;
                flag = 1;
            }
        }
        if (flag == 0)//若有某一趟排序没有发生交换，说明已经有序，提前结束
        {
            return;
        }
    }
}
//此为qsort需要的比较函数
int CmpByAge(const void* e1,const void* e2)
{
    // if(*(int*)e1 < *(int*)e2)
    // {
    //     return -1;
    // }
    // else if(*(int*)e1 == *(int*)e2)
    // {
    //     return 0;
    // }
    // else
    // {
    //     return 1;
    // }
    //思路错误，考虑到比较的是Peoinfo类型的数据，所以要转换成Peoinfo类型在进行比较
    return ((Peoinfo*)e1)->age - ((Peoinfo*)e2)->age;
}
void SortByAge(Contact* pc)
{
    //鹏哥借助qsort来排序
    qsort(pc,pc->count,sizeof(Peoinfo),CmpByAge);//这里比较函数传入函数指针即可
    //void qsort(void *_Base, size_t num, size_t width, int (*_pfcmp)(const void *, const void *))
    //四个参数依次是 要排序元素的起点，要排序元素的个数，待排序元素的大小，比较函数（返回类型为int）
}
void SortByTel(Contact* pc)
{

}
void SortContact(Contact* pc)
{
    char tag[10] = { 0 };
    printf("请输入排序依据\n");
    scanf("%s",tag);
    if(strcmp("姓名",tag) == 0)
    {
        SortByName(pc);
    }
    if(strcmp("年龄",tag) == 0)
    {
        SortByAge(pc);
    }
    if(strcmp("电话",tag) == 0)
    {
        SortByTel(pc);
    }
}


void SaveContacr(const Contact* pc)
{
    FILE* fpWrite = fopen("contact.txt","wb");
    if(fpWrite == NULL)
    {
        perror("SaveContact");
        return;
    }
    int i = 0;
    for(i = 0;i < pc->count;i++)
    {
        fwrite(pc->data+i,sizeof(pc->data[0]),1,fpWrite);
        //第二个参数也可用sizeof(PeoInfo)
    }
    fclose(fpWrite);
    fpWrite = NULL;
}